package org.apereo.cas.authentication;

import org.apereo.cas.authentication.principal.Principal;
import org.springframework.core.Ordered;

import java.security.GeneralSecurityException;

/**
 * An authentication handler authenticates a single credential. In many cases credentials are authenticated by
 * comparison with data in a system of record such as LDAP directory or database.
 *身份验证处理程序对单个凭据进行身份验证。在许多情况下，凭据由
 *
 * 与记录系统（如LDAP目录或数据库）中的数据进行比较。
 * @author Marvin S. Addison
 * @since 4.0.0
 */
@FunctionalInterface
public interface AuthenticationHandler extends Ordered {

    /** Attribute name containing collection of handler names that successfully authenticated credential.
     * 包含成功验证凭据的处理程序名称集合的属性名。
     * */
    String SUCCESSFUL_AUTHENTICATION_HANDLERS = "successfulAuthenticationHandlers";

    /**
     * Authenticates the given credential. There are three possible outcomes of this process, and implementers
     * MUST adhere to the following contract:
     **验证给定凭据。这个过程有三种可能的结果，以及实现者
     *
     * *必须遵守以下合同：
     * <ol>
     *     <li>Success -- return {@link AuthenticationHandlerExecutionResult}</li>
     *     <li>Failure（失败） -- throw {@link GeneralSecurityException}</li>
     *     <li>Indeterminate（不确定） -- throw {@link PreventedException}</li>
     * </ol>
     *
     * @param credential The credential to authenticate.
     *credential要进行身份验证的凭据。
     *
     * @return A result object containing metadata about a successful authentication event that includes at
     * a minimum the name of the handler that authenticated the credential and some credential metadata.
     * The following data is optional:
     *
     * @return 包含有关成功身份验证事件的元数据的结果对象，该事件包括
     *
     * 对凭证和某些凭证元数据进行身份验证的处理程序的最小名称。
     *
     * 以下数据是可选的：
     * <ul>
     *     <li>{@link Principal}</li>
     *     <li>Messages issued by the handler about the credential (e.g. impending password expiration warning)</li>
     *     处理程序发出的有关凭据的消息（例如即将到来的密码过期警告）
     * </ul>
     *
     * @throws GeneralSecurityException On authentication failures where the root cause is security related,
     * e.g. invalid credential. Implementing classes SHOULD be as specific as possible in communicating the reason for
     * authentication failure. Recommendations for common cases:
     * 如果根本原因是与安全相关的身份验证失败，则一般安全例外，
     *
     * *例如，无效凭证。实现类应该尽可能具体地传达
     *
     * *身份验证失败。常见案例建议：
     * <ul>
     *     <li>Bad password: {@code javax.security.auth.login.FailedLoginException}</li>
     *     <li>Expired（过期） password: {@code javax.security.auth.login.CredentialExpiredException}</li>
     *     <li>User account expired: {@code javax.security.auth.login.AccountExpiredException}</li>
     *     <li>User account locked（被锁）: {@code javax.security.auth.login.AccountLockedException}</li>
     *     <li>User account not found（没有找到）: {@code javax.security.auth.login.AccountNotFoundException}</li>
     *     <li>Time of authentication not allowed（不允许身份验证时间）: {@code org.apereo.cas.authentication.InvalidLoginTimeException}</li>
     *     <li>Location of authentication not allowed（不允许身份验证的位置）: {@code org.apereo.cas.authentication.InvalidLoginLocationException}</li>
     *     <li>Expired X.509 certificate: {@code java.security.cert.CertificateExpiredException}</li>
     * </ul>
     * @throws PreventedException On errors that prevented authentication from occurring. Implementing classes SHOULD
     * take care to（注意） populate（填充） the cause, where applicable, with the error that prevented authentication.
     */
    AuthenticationHandlerExecutionResult authenticate(Credential credential) throws GeneralSecurityException, PreventedException;
    
    /**
     * Determines whether the handler has the capability to authenticate the given credential. In practical terms,
     * the {@link #authenticate(Credential)} method MUST be capable of processing a given credential if
     * {@code supports} returns true on the same credential.
     **确定处理程序是否具有对给定凭据进行身份验证的功能。实际上，
     *
     * *{@link#authenticate（Credential）}方法必须能够处理给定的凭据，如果
     *
     * *{@code supports}在同一凭证上返回true。
     * @param credential The credential to check.
     *
     * @return True if the handler supports the Credential, false otherwise.
     */
    default boolean supports(final Credential credential) {
        return false;
    }
    
    /**
     * Gets a unique name for this authentication handler within the Spring context that contains it.
     * For implementations that allow setting a unique name, deployers MUST take care to ensure that every
     * handler instance has a unique name.
     **获取包含此身份验证处理程序的Spring上下文中的唯一名称。
     *
     * *对于允许设置唯一名称的实现，部署人员必须注意确保
     *
     * *处理程序实例具有唯一的名称。
     * @return Unique name within a Spring context.
     */
    default String getName() {
        return this.getClass().getSimpleName();
    }

    @Override
    default int getOrder() {
        return Integer.MAX_VALUE;
    }
}
